// import { hexMD5 } from './md5';
/**
 * 通用js方法封装处理
 * Copyright (c) 2019 ruoyi
 */
/**
 * util:业务无关的工具方法
 */

// export function encryptionPwd (value)  {
//   return hexMD5(value+ "kupeiot")
// }

const sessionStorage = {
  set(key, value) {
    window.sessionStorage.setItem(key, JSON.stringify(value))
  },
  get(key) {
    const jsonString = window.sessionStorage.getItem(key)
    if (jsonString === 'undefined') {
      sessionStorage.remove(key)
      return null
    }
    return jsonString ? JSON.parse(jsonString) : null
  },
  remove(key) {
    window.sessionStorage.removeItem(key)
  },
  clear() {
    window.sessionStorage.clear()
  }
}

const localStorage = {
  set(key, value) {
    window.localStorage.setItem(key, JSON.stringify(value))
  },
  get(key) {
    const jsonString = window.localStorage.getItem(key)
    return jsonString ? JSON.parse(jsonString) : null
  },
  remove(key) {
    window.localStorage.removeItem(key)
  },
  clear() {
    window.localStorage.clear()
  }
}

// 日期格式化
export function parseTime(time, pattern) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    } else if (typeof time === 'string') {
      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '')
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

// 表单重置
export function resetForm(refName) {
  if (this.$refs[refName]) {
    this.$refs[refName].resetFields()
  }
}

// 添加日期范围
export function addDateRange(params, dateRange, propName) {
  const search = params
  search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
  dateRange = Array.isArray(dateRange) ? dateRange : []
  if (typeof (propName) === 'undefined') {
    search.params['beginTime'] = dateRange[0]
    search.params['endTime'] = dateRange[1]
  } else {
    search.params['begin' + propName] = dateRange[0]
    search.params['end' + propName] = dateRange[1]
  }
  return search
}

// 回显数据字典
export function selectDictLabel(datas, value) {
  if (value === undefined) {
    return ''
  }
  var actions = []
  Object.keys(datas).some((key) => {
    if (datas[key].value == ('' + value)) {
      actions.push(datas[key].label)
      return true
    }
  })
  if (actions.length === 0) {
    actions.push(value)
  }
  return actions.join('')
}

// 回显数据字典（字符串数组）
export function selectDictLabels(datas, value, separator) {
  if (value === undefined) {
    return ''
  }
  var actions = []
  var currentSeparator = undefined === separator ? ',' : separator
  var temp = value.split(currentSeparator)
  Object.keys(value.split(currentSeparator)).some((val) => {
    var match = false
    Object.keys(datas).some((key) => {
      if (datas[key].value == ('' + temp[val])) {
        actions.push(datas[key].label + currentSeparator)
        match = true
      }
    })
    if (!match) {
      actions.push(temp[val] + currentSeparator)
    }
  })
  return actions.join('').substring(0, actions.join('').length - 1)
}

// 字符串格式化(%s )
export function sprintf(str) {
  var args = arguments; var flag = true; var i = 1
  str = str.replace(/%s/g, function() {
    var arg = args[i++]
    if (typeof arg === 'undefined') {
      flag = false
      return ''
    }
    return arg
  })
  return flag ? str : ''
}

// 转换字符串，undefined,null等转化为""
export function parseStrEmpty(str) {
  if (!str || str == 'undefined' || str == 'null') {
    return ''
  }
  return str
}

// 数据合并
export function mergeRecursive(source, target) {
  for (var p in target) {
    try {
      if (target[p].constructor == Object) {
        source[p] = mergeRecursive(source[p], target[p])
      } else {
        source[p] = target[p]
      }
    } catch (e) {
      source[p] = target[p]
    }
  }
  return source
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export function handleTree(data, id, parentId, children) {
  const config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  }

  var childrenListMap = {}
  var nodeIds = {}
  var tree = []

  for (const d of data) {
    const parentId = d[config.parentId]
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = []
    }
    nodeIds[d[config.id]] = d
    childrenListMap[parentId].push(d)
  }

  for (const d of data) {
    const parentId = d[config.parentId]
    if (nodeIds[parentId] == null) {
      tree.push(d)
    }
  }

  for (const t of tree) {
    adaptToChildrenList(t)
  }

  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]]
    }
    if (o[config.childrenList]) {
      for (const c of o[config.childrenList]) {
        adaptToChildrenList(c)
      }
    }
  }
  return tree
}

/**
* 参数处理
* @param {*} params  参数
*/
export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName]
    var part = encodeURIComponent(propName) + '='
    if (value !== null && typeof (value) !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && typeof (value[key]) !== 'undefined') {
            const params = propName + '[' + key + ']'
            var subPart = encodeURIComponent(params) + '='
            result += subPart + encodeURIComponent(value[key]) + '&'
          }
        }
      } else {
        result += part + encodeURIComponent(value) + '&'
      }
    }
  }
  return result
}

// 验证是否为blob格式
export async function blobValidate(data) {
  try {
    const text = await data.text()
    JSON.parse(text)
    return false
  } catch (error) {
    return true
  }
}
/**
*日期对象转为日期字符串
  *@param date 需要格式化的日期对象
    *@param sFormat 输出格式, 默认为yyyy - MM - dd                         年：y，月：M，日：d，时：h，分：m，秒：s
      *@example  formatDate(new Date())                                "2017-02-28"
        *@example  formatDate(new Date(), 'yyyy-MM-dd')                   "2017-02-28"
          *@example  formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss')         "2017-02-28 09:24:00"
            *@example  formatDate(new Date(), 'hh:mm')                       "09:24"
              *@example  formatDate(new Date(), 'yyyy-MM-ddTHH:mm:ss+08:00')   "2017-02-28T09:24:00+08:00"
                *@returns { string }
*/
export async function formatDate(date, sFormat = 'yyyy-MM-dd') {
  if (!date) {
    return ''
  }
  // iOS系统new Date('2017-02-28 09:24:00')会报错，针对形如yyyy-MM-dd HH:mm:ss的字符额外处理
  if (typeof date === 'string' && date.length === 19 && !date.includes('T')) {
    // eslint-disable-next-line no-param-reassign
    date = date.replace(/-/g, '/')
  }
  // eslint-disable-next-line no-param-reassign
  date = new Date(date)
  const time = {
    Year: 0,
    TYear: '0',
    Month: 0,
    TMonth: '0',
    Day: 0,
    TDay: '0',
    Hour: 0,
    THour: '0',
    hour: 0,
    Thour: '0',
    Minute: 0,
    TMinute: '0',
    Second: 0,
    TSecond: '0',
    Millisecond: 0
  }
  time.Year = date.getFullYear()
  time.TYear = String(time.Year).substr(2)
  time.Month = date.getMonth() + 1
  time.TMonth = time.Month < 10 ? '0' + time.Month : String(time.Month)
  time.Day = date.getDate()
  time.TDay = time.Day < 10 ? '0' + time.Day : String(time.Day)
  time.Hour = date.getHours()
  time.THour = time.Hour < 10 ? '0' + time.Hour : String(time.Hour)
  time.hour = time.Hour < 13 ? time.Hour : time.Hour - 12
  time.Thour = time.hour < 10 ? '0' + time.hour : String(time.hour)
  time.Minute = date.getMinutes()
  time.TMinute = time.Minute < 10 ? '0' + time.Minute : String(time.Minute)
  time.Second = date.getSeconds()
  time.TSecond = time.Second < 10 ? '0' + time.Second : String(time.Second)
  time.Millisecond = date.getMilliseconds()

  return sFormat
    .replace(/yyyy/gi, String(time.Year))
    .replace(/yyy/gi, String(time.Year))
    .replace(/yy/gi, time.TYear)
    .replace(/y/gi, time.TYear)
    .replace(/MM/g, time.TMonth)
    .replace(/M/g, String(time.Month))
    .replace(/dd/gi, time.TDay)
    .replace(/d/gi, String(time.Day))
    .replace(/HH/g, time.THour)
    .replace(/H/g, String(time.Hour))
    .replace(/hh/g, time.Thour)
    .replace(/h/g, String(time.hour))
    .replace(/mm/g, time.TMinute)
    .replace(/m/g, String(time.Minute))
    .replace(/ss/gi, time.TSecond)
    .replace(/s/gi, String(time.Second))
    .replace(/fff/gi, String(time.Millisecond))
}

// 去除字符串两边空格
export async function trim(str) {
  if (str === null || str === undefined) {
    return ''
  }
  if (typeof str !== 'string') {
    return str
  }
  return String(str).replace(/(^\s+)|(\s+$)/g, '')
}

// 计算文件大小
export async function fileSize(size) {
  size = Number(size)
  if (size < 1024) {
    return size + 'B'
  }
  if (size < 1024 * 1024) {
    return (size / 1024).toFixed(1) + 'KB'
  }
  if (size < 1024 * 1024 * 1024) {
    return (size / 1024 / 1024).toFixed(1) + 'MB'
  }
  return size
}

// 开始日期和结束日期如果相等，则返回一个日期，否则返回日期范围
export async function formatDateRange(startDate, endDate) {
  const start = formatDate(startDate)
  const end = formatDate(endDate)
  return start === end ? start : start + ' ~' + end
}

/**
* uuid 形如：29cbeabba2894d04ac2e3ea99200d937
*/
export async function uuid() {
  return uuidv4().replace(/\-/g, '')
}

/**
* 复制对象
*/
export async function clone(obj) {
  if (obj && obj instanceof Object) {
    return JSON.parse(JSON.stringify(obj))
  }
  return obj
}

/**
* 把数组转为tree结构
*/
export async function listToTree(
  list,
  parentId = '0',
  childrenProp = 'children',
  parentProp = 'parentId'
) {
  const nodes = clone(list).filter(item => item[parentProp] === parentId)
  nodes.forEach(item => {
    const childrenNodes = listToTree(list, item.id, childrenProp, parentProp)
    if (childrenNodes && childrenNodes.length) {
      item[childrenProp] = childrenNodes
    }
  })
  return nodes
}

/**
* 把树结构转为数组
*/
export async function treeToList(tree, childrenProp = 'children') {
  if (!isArray(tree)) {
    tree = [tree]
  }
  let list = []
  clone(tree).forEach(item => {
    list.push(item)
    const childrenNodes = item[childrenProp]
    if (childrenNodes && childrenNodes.length) {
      list = [...list, ...treeToList(childrenNodes, childrenProp)]
    }
  })
  list.forEach(item => {
    delete item[childrenProp]
  })
  return list
}

export async function isJsonString(str) {
  try {
    if (typeof JSON.parse(str) === 'object') {
      return true
    }
  } catch (e) {
    return false
  }
  return false
}

export async function isNumber(value) {
  return !isNaN(Number(value))
}

export async function isString(str) {
  return typeof str === 'string' || str instanceof String
}

export async function isArray(arg) {
  return Object.prototype.toString.call(arg) === '[object Array]'
}

export async function isBlank(str) {
  return str === null || str === undefined || trim(str) === ''
}

export async function isNotBlank(str) {
  return !isBlank(str)
}

/**
* 判断两个数组数据是否相等
* @param arr1
* @param arr2
* @returns {boolean}
*/
export async function assertArraysEqual(arr1, arr2) {
  if (!isArray(arr1) || !isArray(arr2)) {
    throw new Error('非法参数，非数组')
  }
  if (arr1.length !== arr2.length) {
    return false
  }
  return JSON.stringify(arr1.sort()) === JSON.stringify(arr2.sort())
}

/**
* 文件下载
* @param blob 文件流数据
* @param fileName 文件名,包含后缀 如：abc.xlsx
*/
export async function downloadBlob(blob, fileName) {
  try {
    const href = window.URL.createObjectURL(blob) // 创建下载的链接
    if (window.navigator.msSaveBlob) {
      window.navigator.msSaveBlob(blob, fileName)
    } else {
      // 谷歌浏览器 创建a标签 添加download属性下载
      const downloadElement = document.createElement('a')
      downloadElement.href = href
      downloadElement.target = '_blank'
      downloadElement.download = fileName
      document.body.appendChild(downloadElement)
      downloadElement.click() // 点击下载
      document.body.removeChild(downloadElement) // 下载完成移除元素
      window.URL.revokeObjectURL(href) // 释放掉blob对象
    }
  } catch (e) {
    this.$message({
      type: 'error',
      message: fileName + '下载失败！'
    })
  }
}

/**
* 可取消的 Promise；包装Promise添加cancel方法
* 场景：当第一次请求时长大于第二次时，为了避免第一次结果覆盖第二次，则应该在请求第二次时，取消第一次请求
*/
export async function makeCancelable(promise) {
  let hasCanceled_ = false
  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then(val =>
      hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)
    )
    promise.catch(error =>
      hasCanceled_ ? reject({ isCanceled: true }) : reject(error)
    )
  })
  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true
    }
  }
}

export {
  sessionStorage,
  localStorage
}
